package com.base.data.elasticsearch.core.operation;

import com.base.data.elasticsearch.core.BaseMultiGetResultMapper;
import com.base.data.elasticsearch.core.BaseResultsExtractor;
import com.base.data.elasticsearch.core.BaseResultsMapper;
import com.base.data.elasticsearch.core.BaseSearchResultMapper;
import com.base.data.elasticsearch.core.convert.BaseElasticsearchConverter;
import com.base.data.elasticsearch.core.mapping.BaseElasticsearchPersistentEntity;
import com.base.data.elasticsearch.core.operation.BaseElasticsearchOperation;
import com.base.data.elasticsearch.core.query.*;
import com.base.data.elasticsearch.core.query.simplify.SearchQuery;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.cluster.metadata.AliasMetaData;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.script.Script;
import org.elasticsearch.search.aggregations.Aggregations;
import org.springframework.data.domain.Page;
import org.springframework.data.util.CloseableIterator;

import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * ElasticsearchOperations
 */
public interface BaseElasticsearchOperations extends BaseElasticsearchOperationScroll {


    //done
    <T> T query(BaseSearchQuery query, BaseResultsExtractor<T> resultsExtractor);

    <T> T query(BaseSearchQuery query, Class<T> clazz);

    /**
     * Execute the query against elasticsearch and return the first returned object
     *
     * @param query
     * @param clazz
     * @return the first matching object
     */
    //done
    <T> T queryForObject(BaseGetQuery query, Class<T> clazz);
    //to test
    <T> T queryForObject(BaseStringQuery query, Class<T> clazz);
    //done
    <T> T queryForObject(BaseCriteriaQuery query, Class<T> clazz);

    /**
     * Execute the query against elasticsearch and return the first returned object using custom mapper
     *
     * @param query
     * @param clazz
     * @param mapper
     * @return the first matching object
     */
    //done
    <T> T queryForObject(BaseGetQuery query, Class<T> clazz, BaseResultsMapper mapper);


    /**
     * Execute the query against elasticsearch and return result as {@link Page}
     *
     * @param query
     * @param clazz
     * @return
     */
    //done
    <T> Page<T> queryForPage(BaseSearchQuery query, Class<T> clazz);
    //to test
    <T> Page<T> queryForPage(BaseStringQuery query, Class<T> clazz);
    //to test
    <T> Page<T> queryForPage(BaseStringQuery query, Class<T> clazz, BaseSearchResultMapper mapper);
    //done
    <T> Page<T> queryForPage(BaseCriteriaQuery query, Class<T> clazz);

    /**
     * Execute the query against elasticsearch and return result as {@link Page} using custom mapper
     *
     * @param query
     * @param clazz
     * @return
     */
    //done
    <T> Page<T> queryForPage(BaseSearchQuery query, Class<T> clazz, BaseSearchResultMapper mapper);



    /**
     * Executes the given {@link BaseSearchQuery} against elasticsearch and return result as {@link CloseableIterator}.
     * <p>
     * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error.
     *
     * @param <T> element return type
     * @param query
     * @param clazz
     * @return
     * @since 1.3
     */
    @Deprecated
    <T> CloseableIterator<T> stream(BaseSearchQuery query, Class<T> clazz);

    <T> CloseableIterator<T> stream(BaseCriteriaQuery query, Class<T> clazz);

    /**
     * Executes the given {@link BaseSearchQuery} against elasticsearch and return result as {@link CloseableIterator} using custom mapper.
     * <p>
     * Returns a {@link CloseableIterator} that wraps an Elasticsearch scroll context that needs to be closed in case of error.
     *
     * @param <T> element return type
     * @param query
     * @param clazz
     * @param mapper
     * @return
     * @since 1.3
     */
    @Deprecated
    <T> CloseableIterator<T> stream(BaseSearchQuery query, Class<T> clazz, BaseSearchResultMapper mapper);


    /**
     * Execute the search query against elasticsearch and return result as {@link List}
     *
     * @param query
     * @param clazz
     * @param <T>
     * @return
     */
    //done
    <T> List<T> queryForList(BaseSearchQuery query, Class<T> clazz);
    //to test
    <T> List<T> queryForList(BaseStringQuery query, Class<T> clazz);

    //to test
    <T> List<T> queryForList(BaseCriteriaQuery query, Class<T> clazz);

    /**
     * Execute the query against elasticsearch and return ids
     *
     * @param query
     * @return
     */

    //done
    <T> List<String> queryForIds(BaseSearchQuery query);

    /**
     * return number of elements found by given query
     *
     * @param query
     * @param clazz
     * @return
     */
    //done
    <T> long count(BaseSearchQuery query, Class<T> clazz);

    //to test
    <T> long count(BaseCriteriaQuery query, Class<T> clazz);

    /**
     * return number of elements found by given query
     *
     * @param query
     * @return
     */
    //done
    <T> long count(BaseSearchQuery query);

    /**
     * Execute a multiGet against elasticsearch for the given ids
     *
     * @param searchQuery
     * @param clazz
     * @return
     */
    //done
    <T> LinkedList<T> multiGet(BaseSearchQuery searchQuery, Class<T> clazz);

    /**
     * Execute a multiGet against elasticsearch for the given ids with MultiGetResultMapper
     *
     * @param searchQuery
     * @param clazz
     * @param multiGetResultMapper
     * @return
     */
    //done
    <T> LinkedList<T> multiGet(BaseSearchQuery searchQuery, Class<T> clazz, BaseMultiGetResultMapper multiGetResultMapper);

    /**
     * Index an object. Will do save or update
     *
     * @param query
     * @return returns the document id
     */
    //done
    String index(BaseIndexQuery query);

    @Deprecated
    UpdateResponse update(BaseUpdateQuery query);
    //done
    UpdateResponse update(UpdateRequest request);
    //done
    <T> UpdateResponse update(UpdateRequest request, Class<T> clazz);

    //done
    void bulkIndex(List<BaseIndexQuery> queries);

    /**
     * async bulk index ,feature version tofixed return callback function
     * @param queries
     */
    void bulkIndexAsync(List<BaseIndexQuery> queries);


    /**
     * Bulk update all objects. Will do update
     *
     * @param queries
     */

    @Deprecated
    void bulkUpdate(List<BaseUpdateQuery> queries);
    //done
    void bulkUpdateRequest(List<UpdateRequest> requests);

    void bulkUpdateRequestAsync(List<UpdateRequest> requests);
    //done
    <T> void bulkUpdateRequest(List<UpdateRequest> requests, Class<T> clazz);

    /**
     * Delete the one object with provided id
     *
     * @param indexName
     * @param type
     * @param id
     * @return documentId of the document deleted
     */
    //done
    String delete(String indexName, String type, String id);



    /**
     * Delete the one object with provided id
     *
     * @param clazz
     * @param id
     * @return documentId of the document deleted
     */
    //done
    <T> String delete(Class<T> clazz, String id);

    /**
     * Delete all records matching the query
     *
     * @param clazz
     * @param query
     */
    //done
    <T> void delete(BaseDeleteQuery query, Class<T> clazz);

    //to test
    <T> void delete(BaseCriteriaQuery query, Class<T> clazz);

    /**
     * Delete all records matching the query
     *
     * @param query
     */
    //done
    void delete(BaseDeleteQuery query);

    //兼容之前的api
    <T> Aggregations aggregation(SearchQuery<T> var1);

    <T> Response updateByQuery(SearchQuery<T> var1, Script var2);

    <T> List<T> searchList(SearchQuery<T> searchQuery);



}
